home *** CD-ROM | disk | FTP | other *** search
/ Risc World 5 / Risc World 5.iso / SOFTWARE / Issue5 / PD / DIRSYNC / LegalStuff / ccres / c / _Object < prev    next >
Text File  |  2004-12-01  |  33KB  |  1,015 lines

  1. /* _Object.c
  2.    $Id: _Object.c,v 1.5 2004/12/01 23:22:22 joty Exp $
  3.  
  4.    Copyright (c) 2003-2004 Dave Appleby / John Tytgat
  5.  
  6.    This file is part of CCres.
  7.  
  8.    CCres is free software; you can redistribute it and/or modify
  9.    it under the terms of the GNU General Public License as published by
  10.    the Free Software Foundation; either version 2 of the License, or
  11.    (at your option) any later version.
  12.  
  13.    CCres is distributed in the hope that it will be useful,
  14.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    GNU General Public License for more details.
  17.  
  18.    You should have received a copy of the GNU General Public License
  19.    along with CCres; if not, write to the Free Software
  20.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21.  */
  22.  
  23. #include "ccres.h"
  24.  
  25. #include <string.h>
  26.  
  27. #include <OSLib/ddeutils.h>
  28.  
  29. static FLAGS ObjectHeaderFlags[] = {
  30.     {toolbox_OBJECT_CREATE_ON_LOAD, "toolbox_OBJECT_CREATE_ON_LOAD"},
  31.     {toolbox_OBJECT_SHOW_ON_CREATE, "toolbox_OBJECT_SHOW_ON_CREATE"},
  32.     {toolbox_OBJECT_SHARED        , "toolbox_OBJECT_SHARED"        },
  33.     {toolbox_OBJECT_ANCESTOR      , "toolbox_OBJECT_ANCESTOR"      }
  34. };
  35.  
  36. static OBJECTLIST ObjectHeaderList[] = {
  37.     {iol_FLAGS, "header_flags:", offsetof(toolbox_resource_file_object_base, flags),   ObjectHeaderFlags, ELEMENTS(ObjectHeaderFlags)},
  38.     {iol_INT,   "version:",      offsetof(toolbox_resource_file_object_base, version), NULL,              0                          },
  39.     {iol_PSTR,  "object_name:",  offsetof(toolbox_resource_file_object_base, name),    NULL,              0                          }
  40. };
  41.  
  42. static FLAGS WimpIconFlags[] = {
  43.     {wimp_ICON_TEXT                                                , "wimp_ICON_TEXT"               },
  44.     {wimp_ICON_SPRITE                                              , "wimp_ICON_SPRITE"             },
  45.     {wimp_ICON_BORDER                                              , "wimp_ICON_BORDER"             },
  46.     {wimp_ICON_HCENTRED                                            , "wimp_ICON_HCENTRED"           },
  47.     {wimp_ICON_VCENTRED                                            , "wimp_ICON_VCENTRED"           },
  48.     {wimp_ICON_FILLED                                              , "wimp_ICON_FILLED"             },
  49.     {wimp_ICON_ANTI_ALIASED                                        , "wimp_ICON_ANTI_ALIASED"       },
  50.     {wimp_ICON_NEEDS_HELP                                          , "wimp_ICON_NEEDS_HELP"         },
  51.     {wimp_ICON_INDIRECTED                                          , "wimp_ICON_INDIRECTED"         },
  52.     {wimp_ICON_RJUSTIFIED                                          , "wimp_ICON_RJUSTIFIED"         },
  53.     {wimp_ICON_ALLOW_ADJUST                                        , "wimp_ICON_ALLOW_ADJUST"       },
  54.     {wimp_ICON_HALF_SIZE                                           , "wimp_ICON_HALF_SIZE"          },
  55.     {wimp_ICON_SELECTED                                            , "wimp_ICON_SELECTED"           },
  56.     {wimp_ICON_SHADED                                              , "wimp_ICON_SHADED"             },
  57.     {wimp_ICON_DELETED                                             , "wimp_ICON_DELETED"            }
  58. };
  59.  
  60. static FLAGS WimpIconType[] = {
  61.     {(wimp_BUTTON_ALWAYS            << wimp_ICON_BUTTON_TYPE_SHIFT), "wimp_BUTTON_ALWAYS"           },
  62.     {(wimp_BUTTON_REPEAT            << wimp_ICON_BUTTON_TYPE_SHIFT), "wimp_BUTTON_REPEAT"           },
  63.     {(wimp_BUTTON_CLICK             << wimp_ICON_BUTTON_TYPE_SHIFT), "wimp_BUTTON_CLICK"            },
  64.     {(wimp_BUTTON_RELEASE           << wimp_ICON_BUTTON_TYPE_SHIFT), "wimp_BUTTON_RELEASE"          },
  65.     {(wimp_BUTTON_DOUBLE_CLICK      << wimp_ICON_BUTTON_TYPE_SHIFT), "wimp_BUTTON_DOUBLE_CLICK"     },
  66.     {(wimp_BUTTON_CLICK_DRAG        << wimp_ICON_BUTTON_TYPE_SHIFT), "wimp_BUTTON_CLICK_DRAG"       },
  67.     {(wimp_BUTTON_RELEASE_DRAG      << wimp_ICON_BUTTON_TYPE_SHIFT), "wimp_BUTTON_RELEASE_DRAG"     },
  68.     {(wimp_BUTTON_DOUBLE_DRAG       << wimp_ICON_BUTTON_TYPE_SHIFT), "wimp_BUTTON_DOUBLE_DRAG"      },
  69.     {(wimp_BUTTON_MENU_ICON         << wimp_ICON_BUTTON_TYPE_SHIFT), "wimp_BUTTON_MENU_ICON"        },
  70.     {(wimp_BUTTON_DOUBLE_CLICK_DRAG << wimp_ICON_BUTTON_TYPE_SHIFT), "wimp_BUTTON_DOUBLE_CLICK_DRAG"},
  71.     {(wimp_BUTTON_RADIO             << wimp_ICON_BUTTON_TYPE_SHIFT), "wimp_BUTTON_RADIO"            },
  72.     {(wimp_BUTTON_WRITE_CLICK_DRAG  << wimp_ICON_BUTTON_TYPE_SHIFT), "wimp_BUTTON_WRITE_CLICK_DRAG" },
  73.     {(wimp_BUTTON_WRITABLE          << wimp_ICON_BUTTON_TYPE_SHIFT), "wimp_BUTTON_WRITABLE"         }
  74. };
  75.  
  76. static FLAGS OsColours[] = {
  77.     {os_COLOUR_TRANSPARENT    , "os_COLOUR_TRANSPARENT"    },
  78.     {os_COLOUR_RED            , "os_COLOUR_RED"            },
  79.     {os_COLOUR_GREEN          , "os_COLOUR_GREEN"          },
  80.     {os_COLOUR_BLUE           , "os_COLOUR_BLUE"           },
  81.     {os_COLOUR_CYAN           , "os_COLOUR_CYAN"           },
  82.     {os_COLOUR_MAGENTA        , "os_COLOUR_MAGENTA"        },
  83.     {os_COLOUR_YELLOW         , "os_COLOUR_YELLOW"         },
  84.     {os_COLOUR_WHITE          , "os_COLOUR_WHITE"          },
  85.     {os_COLOUR_VERY_LIGHT_GREY, "os_COLOUR_VERY_LIGHT_GREY"},
  86.     {os_COLOUR_LIGHT_GREY     , "os_COLOUR_LIGHT_GREY"     },
  87.     {os_COLOUR_MID_LIGHT_GREY , "os_COLOUR_MID_LIGHT_GREY" },
  88.     {os_COLOUR_MID_DARK_GREY  , "os_COLOUR_MID_DARK_GREY"  },
  89.     {os_COLOUR_DARK_GREY      , "os_COLOUR_DARK_GREY"      },
  90.     {os_COLOUR_VERY_DARK_GREY , "os_COLOUR_VERY_DARK_GREY" },
  91.     {os_COLOUR_BLACK          , "os_COLOUR_BLACK"          },
  92.     {os_COLOUR_DARK_BLUE      , "os_COLOUR_DARK_BLUE"      },
  93.     {os_COLOUR_LIGHT_YELLOW   , "os_COLOUR_LIGHT_YELLOW"   },
  94.     {os_COLOUR_LIGHT_GREEN    , "os_COLOUR_LIGHT_GREEN"    },
  95.     {os_COLOUR_LIGHT_RED      , "os_COLOUR_LIGHT_RED"      },
  96.     {os_COLOUR_CREAM          , "os_COLOUR_CREAM"          },
  97.     {os_COLOUR_DARK_GREEN     , "os_COLOUR_DARK_GREEN"     },
  98.     {os_COLOUR_ORANGE         , "os_COLOUR_ORANGE"         },
  99.     {os_COLOUR_LIGHT_BLUE     , "os_COLOUR_LIGHT_BLUE"     }
  100. };
  101.  
  102. static FLAGS WimpColour[] = {
  103.     {wimp_COLOUR_WHITE          , "wimp_COLOUR_WHITE"          },
  104.     {wimp_COLOUR_VERY_LIGHT_GREY, "wimp_COLOUR_VERY_LIGHT_GREY"},
  105.     {wimp_COLOUR_LIGHT_GREY     , "wimp_COLOUR_LIGHT_GREY"     },
  106.     {wimp_COLOUR_MID_LIGHT_GREY , "wimp_COLOUR_MID_LIGHT_GREY" },
  107.     {wimp_COLOUR_MID_DARK_GREY  , "wimp_COLOUR_MID_DARK_GREY"  },
  108.     {wimp_COLOUR_DARK_GREY      , "wimp_COLOUR_DARK_GREY"      },
  109.     {wimp_COLOUR_VERY_DARK_GREY , "wimp_COLOUR_VERY_DARK_GREY" },
  110.     {wimp_COLOUR_BLACK          , "wimp_COLOUR_BLACK"          },
  111.     {wimp_COLOUR_DARK_BLUE      , "wimp_COLOUR_DARK_BLUE"      },
  112.     {wimp_COLOUR_YELLOW         , "wimp_COLOUR_YELLOW"         },
  113.     {wimp_COLOUR_LIGHT_GREEN    , "wimp_COLOUR_LIGHT_GREEN"    },
  114.     {wimp_COLOUR_RED            , "wimp_COLOUR_RED"            },
  115.     {wimp_COLOUR_CREAM          , "wimp_COLOUR_CREAM"          },
  116.     {wimp_COLOUR_DARK_GREEN     , "wimp_COLOUR_DARK_GREEN"     },
  117.     {wimp_COLOUR_ORANGE         , "wimp_COLOUR_ORANGE"         },
  118.     {wimp_COLOUR_LIGHT_BLUE     , "wimp_COLOUR_LIGHT_BLUE"     },
  119.     {wimp_COLOUR_TRANSPARENT    , "wimp_COLOUR_TRANSPARENT"    }
  120. };
  121.  
  122. static FLAGS CmpFlags[] = {
  123.     {toolbox_NULL_COMPONENT, "toolbox_NULL_COMPONENT"},
  124.     {toolbox_WINDOW_FOCUS  , "toolbox_WINDOW_FOCUS"  }
  125. };
  126.  
  127.  
  128. void report(PDATA data, PSTR ptr, PSTR pszFmt, ...)
  129. {
  130.     va_list list;
  131.     PSTR p;
  132.     int nRow;
  133.     char achError[1024];
  134.  
  135.     va_start(list, pszFmt);
  136.     vsprintf(achError, pszFmt, list);
  137.     va_end(list);
  138.     for (nRow = 1, p = data->pszIn; p < ptr; p++) {
  139.         if (*p < ' ') {
  140.             nRow++;
  141.         }
  142.     }
  143.     if (!data->fThrowback) {
  144.         ddeutils_throwback_start();
  145.         data->fThrowback = TRUE;
  146.     }
  147.     ddeutils_throwback_send(ddeutils_THROWBACK_INFO_DETAILS, data->achTextFile, nRow, ddeutils_SEVERITY_ERROR, achError);
  148. }
  149.  
  150.  
  151. static PSTR parse(PDATA data, PSTR pszIn, PSTR pszEntry)
  152. {
  153.     PSTR p, pszEnd;
  154.     int cb;
  155.     char ch, ch0;
  156.  
  157.     ch0 = *pszEntry++;        // it's faster to check first char before calling __strnicmp
  158.     cb = strlen(pszEntry);
  159.     p = pszIn;
  160.     pszEnd = &data->pszIn[data->cbIn] - cb;
  161.     while ((ch = *p++) != '}' && p < pszEnd) {
  162.         if (ch == ':' || ch == '#') {  // skip values and comments
  163.             while (*p++ >= ' ' && p < pszEnd) ;
  164.         } else if (ch == ch0 && __strnicmp(p, pszEntry, cb) == 0) {
  165.             return(p + cb);
  166.         }
  167.     }
  168.     report(data, pszIn, "Missing entry '%s'", --pszEntry);
  169.     return(NULL);
  170. }
  171.  
  172.  
  173. static BOOL add_to_reloc_table(PRELOCTABLE pRelocTable, int nEntry, int nTable)
  174. {
  175.     PRELOC pReloc;
  176.     int nReloc;
  177.  
  178.     nReloc = pRelocTable->ref++;
  179.     pRelocTable->pReloc[nReloc].offset = nEntry;
  180.     pRelocTable->pReloc[nReloc].type = nTable;
  181.  
  182.     if (pRelocTable->ref >= (pRelocTable->max - sizeof(RELOC))) {
  183.         nReloc = pRelocTable->max * 3 / 2;
  184.         if ((pReloc = MyAlloc(nReloc * sizeof(RELOC))) == NULL) {
  185.             return(FALSE);
  186.         }
  187.         memcpy((PSTR) pReloc, (PSTR) pRelocTable->pReloc, pRelocTable->max * sizeof(RELOC));
  188.         MyFree(pRelocTable->pReloc);
  189.         pRelocTable->pReloc = pReloc;
  190.         pRelocTable->max = nReloc;
  191.     }
  192.     return(TRUE);
  193. }
  194.  
  195.  
  196. // may be trailing spaces after closing quote
  197. // may be no quotes at all
  198. // report imbalance
  199. static PSTR remove_quotes(PDATA data, PSTR pszEntry)
  200. {
  201.     int cb, cbTerm;
  202.     char ch;
  203.  
  204.     cbTerm = strlen(pszEntry);
  205.     if (pszEntry[0] == '\"') {
  206.         for (cb = cbTerm - 1; cb > 0; cb--) {
  207.             if ((ch = pszEntry[cb]) == '\"') {
  208.                 pszEntry[cbTerm] = ' ';        // keep line numbering correct for report()
  209.                 pszEntry[cb] = '\0';
  210.                 return(pszEntry + 1);
  211.             } else if (ch != ' ') {
  212.                 break;                        // unmatched quotes
  213.             }
  214.         }
  215.     } else if (pszEntry[cbTerm - 1] != '\"') {
  216. // if there are no quotes, how do we know if there are supposed to be trailing spaces or not?
  217. // on balance probably best to leave them in?
  218.         return(pszEntry);
  219.     }
  220.     report(data, pszEntry, "Unmatched quotes '%s'", pszEntry);
  221.     return(pszEntry);
  222. }
  223.  
  224.  
  225. static BOOL put_string(PDATA data, PSTR pszIn, int nOffset, PSTR object, PSTRINGLIST StringList)
  226. {
  227.     PSTRINGTABLE pTable;
  228.     PINT pInt;
  229.     PSTR pszEntry, pszLimit, pstr;
  230.     int cb, cbEntry, cbLimit, nTable;
  231.  
  232.     if (StringList->nTable == iol_STRING) {
  233.         pTable = &data->StringTable;
  234.         nTable = toolbox_RELOCATE_STRING_REFERENCE;
  235.     } else if (StringList->nTable == iol_MSG) {
  236.         pTable = &data->MessageTable;
  237.         nTable = toolbox_RELOCATE_MSG_REFERENCE;
  238.     } else {
  239.         error("Unexpected string table type (%d)", StringList->nTable);
  240.         return(FALSE);
  241.     }
  242.     cbEntry = 0;
  243. LOG(("\nLookup: %s", StringList->pszEntry));
  244.     if ((pszEntry = parse(data, pszIn, StringList->pszEntry)) != NULL) {
  245.         cbEntry = my_strcpy(&pTable->pstr[pTable->ref], remove_quotes(data, pszEntry));
  246.     }
  247. LOG(("'%s' (%d)", &pTable->pstr[pTable->ref], cbEntry));
  248.     cbLimit = 0;
  249.     if (StringList->pszLimit != NULL && (pszLimit = parse(data, pszIn, StringList->pszLimit)) != NULL) {
  250.         if (pszLimit[0] == '*') {
  251.             cbLimit = (cbEntry == 0) ? 0 : (cbEntry + 1);
  252.         } else {
  253.             cbLimit = __atoi(&pszLimit);
  254.             cbLimit = (cbLimit > 0 && cbLimit <= cbEntry) ? (cbEntry + 1) : cbLimit;
  255.         }
  256.     }
  257.     pInt = (PINT) &object[StringList->nEntry];
  258.     *pInt = (cbEntry > 0 || cbLimit > 0) ? pTable->ref : -1;
  259.     add_to_reloc_table(&data->RelocTable, StringList->nEntry + nOffset, nTable);
  260.     if (StringList->pszLimit != NULL) {
  261.         pInt = (PINT) &object[StringList->nLimit];
  262.         *pInt = cbLimit;
  263.     }
  264. //    if (cbEntry > 0) {
  265.     if (cbEntry > 0 || cbLimit > 0) {
  266.         pTable->ref += cbEntry + 1;
  267.         if (pTable->ref > (pTable->max - 256)) {
  268.             cb = pTable->max * 3 / 2;
  269.             if ((pstr = MyAlloc(cb)) == NULL) {
  270.                 return(FALSE);
  271.             }
  272.             memcpy(pstr, pTable->pstr, pTable->max);
  273.             MyFree(pTable->pstr);
  274.             pTable->pstr = pstr;
  275.             pTable->max = cb;
  276.         }
  277.     }
  278.     return(TRUE);
  279. }
  280.  
  281.  
  282. static BOOL put_tstring(PDATA data, PSTR pszIn, int nOffset, PSTR object, PSTRINGLIST StringList)
  283. {
  284.     PSTRINGTABLE pTable;
  285.     PINT pInt;
  286.     PSTR pszEntry, pszLimit, pstr;
  287.     int cb, cbEntry, cbLimit, nTable;
  288.  
  289.     pTable = &data->StringTable;
  290.     nTable = toolbox_RELOCATE_STRING_REFERENCE;
  291.  
  292.     cbEntry = 0;
  293.     if ((pszEntry = parse(data, pszIn, StringList->pszEntry)) != NULL) {
  294.         pstr = &pTable->pstr[pTable->ref];
  295.         cbEntry = my_strcpy(pstr, remove_quotes(data, pszEntry));
  296.         pstr[cbEntry] = '\r';
  297.     }
  298.     cbLimit = 0;
  299.     if (StringList->pszLimit != NULL && (pszLimit = parse(data, pszIn, StringList->pszLimit)) != NULL) {
  300.         if (pszLimit[0] == '*') {
  301.             cbLimit = (cbEntry == 0) ? 0 : (cbEntry + 1);
  302.         } else {
  303.             cbLimit = __atoi(&pszLimit);
  304.             cbLimit = (cbLimit > 0 && cbLimit <= cbEntry) ? (cbEntry + 1) : cbLimit;
  305.         }
  306.     }
  307.     pInt = (PINT) &object[StringList->nEntry];
  308.     *pInt = (cbEntry > 0 || cbLimit > 0) ? (pTable->ref - nOffset) : -1;
  309.     if (StringList->pszLimit != NULL) {
  310.         pInt = (PINT) &object[StringList->nLimit];
  311.         *pInt = cbLimit;
  312.     }
  313.     if (cbEntry > 0) {
  314.         pTable->ref += cbEntry + 1;
  315.         if (pTable->ref > (pTable->max - 256)) {
  316.             cb = pTable->max * 3 / 2;
  317.             if ((pstr = MyAlloc(cb)) == NULL) {
  318.                 return(FALSE);
  319.             }
  320.             memcpy(pstr, pTable->pstr, pTable->max);
  321.             MyFree(pTable->pstr);
  322.             pTable->pstr = pstr;
  323.             pTable->max = cb;
  324.         }
  325.     }
  326.     return(TRUE);
  327. }
  328.  
  329.  
  330. static PSTR string_from_table(PSTR pszTable, int ref)
  331. {
  332.     static PSTR pszNull = "";
  333.     PSTR pstr, p;
  334.     char ch;
  335.  
  336.     if (pszTable == NULL || ref < 0) {
  337.         return(pszNull);
  338.     }
  339. // modified to handle Template \n terminated strings
  340. //    return(&pszTable[ref]);
  341.     pstr = p = &pszTable[ref];
  342.     while ((ch = *p++) != '\0' && ch != '\n' && ch != '\r') ;
  343.     *(p - 1) = '\0';
  344.     return(pstr);
  345. }
  346.  
  347.  
  348. static void get_string(FILE * hf, PSTR pszStringTable, PSTR pszMessageTable, PSTR object, PSTRINGLIST StringList, PSTR pszIndent)
  349. {
  350.     PINT pInt;
  351.     PSTR pstr, qstr, string_table;
  352.     int cbLimit, ref;
  353.  
  354.     if (StringList->nTable == iol_STRING) {
  355.         string_table = pszStringTable;
  356.     } else if (StringList->nTable == iol_MSG) {
  357.         string_table = pszMessageTable;
  358.     } else {
  359.         error("Unexpected string table type (%d)", StringList->nTable);
  360.         return;
  361.     }
  362.     pInt = (PINT) &object[StringList->nEntry];
  363. LOG(("get_string(object[%x]) = %x", StringList->nEntry, *pInt));
  364.     pstr = "";
  365.     if ((ref = *pInt) >= 0 && (qstr = string_from_table(string_table, ref)) != NULL) {
  366.         pstr = qstr;
  367.     }
  368. LOG(("entry=%s\"%s\"\n", StringList->pszEntry, pstr));
  369.     fprintf(hf, "%s\"%s\"\n", StringList->pszEntry, pstr);
  370.     if (StringList->pszLimit != NULL) {
  371.         pInt = (PINT) &object[StringList->nLimit];
  372.         cbLimit = *pInt;
  373.         fputs(pszIndent, hf);
  374.         if (cbLimit > (strlen(pstr) + 1)) {
  375.             fprintf(hf, "%s%d\n", StringList->pszLimit, cbLimit);
  376.         } else {
  377.             fprintf(hf, "%s*\n", StringList->pszLimit);
  378.         }
  379.     }
  380. }
  381.  
  382.  
  383. static void get_tstring(FILE * hf, PSTR pszStringTable, PSTR object, PSTRINGLIST StringList, PSTR pszIndent)
  384. {
  385.     PINT pInt;
  386.     PSTR pstr, qstr;
  387.     int cbLimit, ref;
  388.  
  389.     pInt = (PINT) &object[StringList->nEntry];
  390. LOG(("get_tstring(object[%x]) = %x", StringList->nEntry, *pInt));
  391.     pstr = "";
  392.     if ((ref = *pInt) >= 0 && (qstr = string_from_table(pszStringTable, ref)) != NULL) {
  393.         pstr = qstr;
  394.     }
  395. LOG(("entry=%s\"%s\"\n", StringList->pszEntry, pstr));
  396.     fprintf(hf, "%s\"%s\"\n", StringList->pszEntry, pstr);
  397.     if (StringList->pszLimit != NULL) {
  398.         pInt = (PINT) &object[StringList->nLimit];
  399.         cbLimit = *pInt;
  400.         fputs(pszIndent, hf);
  401.         if (cbLimit > (strlen(pstr) + 1)) {
  402.             fprintf(hf, "%s%d\n", StringList->pszLimit, cbLimit);
  403.         } else if (cbLimit > 0) {
  404.             fprintf(hf, "%s*\n", StringList->pszLimit);
  405.         } else {
  406.             fprintf(hf, "%s\n", StringList->pszLimit);
  407.         }
  408.     }
  409. }
  410.  
  411.  
  412. static bits put_flags(PDATA data, PSTR pstrFlags, PFLAGS pFlags, int nFlags)
  413. {
  414.     PSTR p;
  415.     bits f;
  416.     int n, cb;
  417.     char ch;
  418.  
  419.     f = 0;
  420.     p = pstrFlags;
  421.     while (*p != '\0') {
  422.         while ((ch = *p) > ' ' && ch != '|') p++;
  423.         cb = p - pstrFlags;
  424.         for (n = 0; n < nFlags; n++) {
  425.             if (__strnicmp(pstrFlags, pFlags[n].pstr, cb) == 0 && strlen(pFlags[n].pstr) == cb) {
  426.                 f |= pFlags[n].flag;
  427.                 goto put_flags_next_flag;
  428.             }
  429.         }
  430.         report(data, pstrFlags, "Unknown flag '%.*s'", cb, pstrFlags);
  431.  
  432. put_flags_next_flag:
  433.  
  434.         while ((ch = *p) == ' ' || ch == '|') p++;
  435.         pstrFlags = p;
  436.     }
  437.     return(f);
  438. }
  439.  
  440.  
  441. static void get_flags(FILE * hf, PSTR pszFlags, bits fFlags, PFLAGS pFlags, int nFlags)
  442. {
  443.     PSTR pszOr;
  444.     int cb, n;
  445.     char achBuff[1120];        // =32 x 32 character flags
  446.  
  447.     cb = sprintf(achBuff, "%s", pszFlags);
  448.     pszOr = "";
  449.     for (n = 0; n < nFlags && fFlags != 0; n++) {
  450.         if ((fFlags & pFlags[n].flag) == pFlags[n].flag) {
  451.             cb += sprintf(&achBuff[cb], "%s%s", pszOr, pFlags[n].pstr);
  452.             pszOr = " | ";
  453.             fFlags ^= pFlags[n].flag;
  454.         }
  455.     }
  456.     /* Louzy error message but I don't know yet how I can improve it. */
  457.     if (fFlags != 0)
  458.         error("Not all bits are covered");
  459.     achBuff[cb++] = '\n';
  460.     fwrite(achBuff, cb, 1, hf);
  461. }
  462.  
  463.  
  464. // fInt - value may be a #defined variable or a nunber (hex or decimal)
  465. static int put_enum(PDATA data, PSTR pstrFlags, PFLAGS pFlags, int nFlags, BOOL fInt)
  466. {
  467.     int n;
  468.  
  469.     if (*pstrFlags > ' ') {
  470.         for (n = 0; n < nFlags; n++) {
  471.             if (strcmp(pstrFlags, pFlags[n].pstr) == 0) {
  472.                 return(pFlags[n].flag);
  473.             }
  474.         }
  475.         if (fInt) {
  476.             return(__atoi(&pstrFlags));
  477.         }
  478.         report(data, pstrFlags, "Unknown variable '%s'", pstrFlags);
  479.     }
  480.  
  481.     return(0);
  482. }
  483.  
  484.  
  485. // fInt - value may be a #defined variable or a nunber (hex or decimal)
  486. static void get_enum(FILE * hf, PSTR pszFlags, int fFlags,  PFLAGS pFlags, int nFlags, BOOL fInt)
  487. {
  488.     int cb, n;
  489.     char achBuff[64];        // = 32 + 32 character flags
  490.  
  491.     cb = my_strcpy(achBuff, pszFlags);
  492.     for (n = 0; n < nFlags; n++) {
  493.         if (fFlags == pFlags[n].flag) {
  494.             cb += my_strcpy(&achBuff[cb], pFlags[n].pstr);
  495.             goto get_enum_found;
  496.         }
  497.     }
  498.     if (fInt) {
  499.         cb += sprintf(&achBuff[cb], "&%x", fFlags);
  500.     }
  501.  
  502. get_enum_found:
  503.  
  504.     achBuff[cb++] = '\n';
  505.     fwrite(achBuff, cb, 1, hf);
  506. }
  507.  
  508.  
  509. static bits put_iflags(PDATA data, PSTR pstrFlags)
  510. {
  511.     PFLAGS pFlags;
  512.     PSTR p;
  513.     bits f;
  514.     int n, cb, nFlags;
  515.     char ch;
  516.  
  517.     f = 0;
  518.     p = pstrFlags;
  519.     while (*p != '\0') {
  520.         while ((ch = *p) > ' ' && ch != '|') p++;
  521.         cb = p - pstrFlags;
  522.         pFlags = WimpIconFlags;
  523.         nFlags = ELEMENTS(WimpIconFlags);
  524.         for (n = 0; n < nFlags; n++) {
  525.             if (__strnicmp(pstrFlags, pFlags[n].pstr, cb) == 0 && strlen(pFlags[n].pstr) == cb) {
  526.                 f |= pFlags[n].flag;
  527.                 goto put_iflags_next_flag;
  528.             }
  529.         }
  530.         pFlags = WimpIconType;
  531.         nFlags = ELEMENTS(WimpIconType);
  532.         for (n = 0; n < nFlags; n++) {
  533.             if (strcmp(pstrFlags, pFlags[n].pstr) == 0) {
  534.                 f |= pFlags[n].flag;
  535.                 goto put_iflags_next_flag;
  536.             }
  537.         }
  538.         report(data, pstrFlags, "Unknown flag '%.*s'", cb, pstrFlags);
  539.  
  540. put_iflags_next_flag:
  541.  
  542.         while ((ch = *p) == ' ' || ch == '|') p++;
  543.         pstrFlags = p;
  544.     }
  545.  
  546.     return(f);
  547. }
  548.  
  549.  
  550. static void get_iflags(FILE * hf, PSTR pszFlags, bits fFlags)
  551. {
  552.     PFLAGS pFlags;
  553.     PSTR pszOr;
  554.     int cb, n, nFlags;
  555.     char achBuff[1120];        // =32 x 32 character flags
  556.  
  557.     pFlags = WimpIconFlags;
  558.     nFlags = ELEMENTS(WimpIconFlags);
  559.     cb = sprintf(achBuff, "%s", pszFlags);
  560.     pszOr = "";
  561.     for (n = 0; n < nFlags; n++) {
  562.         if ((fFlags & pFlags[n].flag) == pFlags[n].flag) {
  563.             cb += sprintf(&achBuff[cb], "%s%s", pszOr, pFlags[n].pstr);
  564.             pszOr = " | ";
  565.         }
  566.     }
  567.     pFlags = WimpIconType;
  568.     nFlags = ELEMENTS(WimpIconType);
  569.     fFlags &= wimp_ICON_BUTTON_TYPE;
  570.     for (n = 0; n < nFlags; n++) {
  571.         if (fFlags == pFlags[n].flag) {
  572.             cb += sprintf(&achBuff[cb], "%s%s", pszOr, pFlags[n].pstr);
  573.             break;
  574.         }
  575.     }
  576.     achBuff[cb++] = '\n';
  577.     fwrite(achBuff, cb, 1, hf);
  578. }
  579.  
  580.  
  581. static void put_box(PDATA data, PSTR pstr, os_box * box)
  582. {
  583.     PINT pi;
  584.     int n;
  585.  
  586. LOG(("put_box %s", pstr));
  587.     pi = (PINT) box;
  588.     for (n = 0; n < 4; n++) {
  589.         pi[n] = Eval(data, &pstr);
  590.         pstr++;
  591.     }
  592. LOG(("(%d, %d, %d, %d)", pi[0], pi[1], pi[2], pi[3]));
  593. }
  594.  
  595.  
  596. static void get_box(FILE * hf, PSTR pszBox, os_box * bbox)
  597. {
  598.     fprintf(hf, "%s%d,%d,%d,%d\n", pszBox, bbox->x0, bbox->y0, bbox->x1, bbox->y1);
  599. }
  600.  
  601.  
  602. static void put_coord(PDATA data, PSTR pstr, os_coord * coord)
  603. {
  604.     PINT pi;
  605.     int n;
  606.  
  607. LOG(("put_coord %s", pstr));
  608.     pi = (PINT) coord;
  609.     for (n = 0; n < 2; n++) {
  610.         pi[n] = Eval(data, &pstr);
  611. //LOG(("New pstr = '%s'", pstr));
  612.         pstr++;
  613.     }
  614. LOG(("(%d, %d)", pi[0], pi[1]));
  615. }
  616.  
  617.  
  618. static void get_coord(FILE * hf, PSTR pszCoord, os_coord * coord)
  619. {
  620.     fprintf(hf, "%s%d,%d\n", pszCoord, coord->x, coord->y);
  621. }
  622.  
  623.  
  624. static void put_pstr(PDATA data, PSTR pstr, PSTR pszEntry, int nChars)
  625. {
  626.     int cb;
  627.  
  628.     pszEntry = remove_quotes(data, pszEntry);
  629.     if (nChars != 0 && strlen(pszEntry) == nChars) {
  630.         memcpy(pstr, pszEntry, nChars);
  631.     } else {
  632.         if (data->nFiletypeOut == osfile_TYPE_TEMPLATE) {
  633.             cb = my_strcpy0d(pstr, pszEntry);
  634.             pstr[cb] = '\r';
  635.         } else {
  636.             strcpy(pstr, pszEntry);
  637.         }
  638.     }
  639. }
  640.  
  641.  
  642. static void get_pstr(FILE * hf, PSTR pszEntry, PSTR pszObject, int nEntry, int nChars)
  643. {
  644.     PSTR pszBuff;
  645.  
  646. LOG(("get_pstr(%s, %s)", pszEntry, &pszObject[nEntry]));
  647.     pszBuff = NULL;
  648.     if (nChars == 0) {
  649.         fprintf(hf, "%s\"%s\"\n", pszEntry, string_from_table(pszObject, nEntry));
  650.     } else {
  651.         if ((pszBuff = MyAlloc(nChars + 1)) == NULL) {
  652.             error("Not enough memory to get %s", pszEntry);
  653.         } else {
  654.             my_strncpy0d(pszBuff, &pszObject[nEntry], nChars);
  655. LOG(("b(%s, %s)", pszBuff, pszBuff));
  656.             fprintf(hf, "%s\"%s\"\n", pszEntry, pszBuff);
  657.             MyFree(pszBuff);
  658.         }
  659.     }
  660. }
  661.  
  662.  
  663. void put_objects(PDATA data, PSTR pszIn, int nOffset, PSTR Object, POBJECTLIST ObjectList, int nObjects)
  664. {
  665. PBITS pBits;
  666. PINT pInt;
  667. PSHORT pShort;
  668. PBYTE pByte;
  669. PSTR pszEntry;
  670. int n;
  671.  
  672. LOG(("put_objects(offset:%x)", nOffset));
  673. for (n = 0; n < nObjects; n++, ObjectList++)
  674.   {
  675. LOG(("Item:%s\tOffset:%d\tType:%d", ObjectList->pszEntry, ObjectList->nEntry, ObjectList->nTable));
  676.   switch (ObjectList->nTable)
  677.     {
  678.     case iol_MSG:
  679.     case iol_STRING:
  680.       put_string(data, pszIn, nOffset, Object, (PSTRINGLIST) ObjectList);
  681.       break;
  682.     case iol_TSTRING:
  683.       put_tstring(data, pszIn, nOffset, Object, (PSTRINGLIST) ObjectList);
  684.       break;
  685.     case iol_OBJECT:
  686.       add_to_reloc_table(&data->RelocTable, ObjectList->nEntry, toolbox_RELOCATE_OBJECT_OFFSET);
  687.       break;
  688.     default:
  689.       if ((pszEntry = parse(data, pszIn, ObjectList->pszEntry)) != NULL)
  690.         {
  691.         switch (ObjectList->nTable)
  692.           {
  693.           case iol_FLAGS:
  694.             pBits = (PBITS) &Object[ObjectList->nEntry];
  695.             *pBits = put_flags(data, pszEntry, (PFLAGS) ObjectList->pData, ObjectList->nData);
  696.             break;
  697.           case iol_IFLAGS:
  698.             pBits = (PBITS) &Object[ObjectList->nEntry];
  699.             *pBits = put_iflags(data, pszEntry);
  700.             break;
  701.           case iol_BFLAGS:
  702.             pByte = (PBYTE) &Object[ObjectList->nEntry];
  703.             *pByte = (byte) put_flags(data, pszEntry, (PFLAGS) ObjectList->pData, ObjectList->nData);
  704.             break;
  705.           case iol_ENUM:
  706.             pInt = (PINT) &Object[ObjectList->nEntry];
  707.             *pInt = put_enum(data, pszEntry, (PFLAGS) ObjectList->pData, ObjectList->nData, FALSE);
  708.             break;
  709.           case iol_CMP:
  710.             pInt = (PINT) &Object[ObjectList->nEntry];
  711.             *pInt = put_enum(data, pszEntry, CmpFlags, ELEMENTS(CmpFlags), TRUE);
  712.             break;
  713.           case iol_OSCOL:
  714.             pInt = (PINT) &Object[ObjectList->nEntry];
  715.             *pInt = put_enum(data, pszEntry, OsColours, ELEMENTS(OsColours), FALSE);
  716.             break;
  717.           case iol_BOX:
  718.             put_box(data, pszEntry, (os_box *) &Object[ObjectList->nEntry]);
  719.             break;
  720.           case iol_BITS:
  721.             pBits = (PBITS) &Object[ObjectList->nEntry];
  722.             if (*pszEntry < ' ')
  723.               *pBits = (ObjectList->nData == bits_ACTION) ? ~0 : 0;
  724.             else
  725.               *pBits = (ObjectList->nData == bits_EVAL) ? Eval(data, &pszEntry) : __atoi(&pszEntry);
  726.             break;
  727.           case iol_INT:
  728.             pInt = (PINT) &Object[ObjectList->nEntry];
  729.             *pInt = __atoi(&pszEntry);
  730.             break;
  731.           case iol_SHORT:
  732.             pShort = (PSHORT) &Object[ObjectList->nEntry];
  733.             *pShort = (short) __atoi(&pszEntry);
  734.             break;
  735.           case iol_BYTE:
  736.             pByte = (PBYTE) &Object[ObjectList->nEntry];
  737.             *pByte = (byte) __atoi(&pszEntry);
  738.             break;
  739.           case iol_COORD:
  740.             put_coord(data, pszEntry, (os_coord *) &Object[ObjectList->nEntry]);
  741.             break;
  742.           case iol_SPRITE:
  743.             pBits = (PBITS) &Object[ObjectList->nEntry];
  744.             *pBits = __atoi(&pszEntry);
  745.             add_to_reloc_table(&data->RelocTable, ObjectList->nEntry, toolbox_RELOCATE_SPRITE_AREA_REFERENCE);
  746.             break;
  747.           case iol_PSTR:
  748.             put_pstr(data, &Object[ObjectList->nEntry], pszEntry, ObjectList->nData);
  749.             break;
  750.           case iol_ESG:
  751.             pBits = (PBITS) &Object[ObjectList->nEntry];
  752.             *pBits |= (__atoi(&pszEntry) << wimp_ICON_ESG_SHIFT);
  753.             break;
  754.           case iol_WCOL:
  755.             pByte = (PBYTE) &Object[ObjectList->nEntry];
  756.             *pByte = (byte) put_enum(data, pszEntry, WimpColour, ELEMENTS(WimpColour), FALSE);
  757.             break;
  758.           case iol_BCOLS:
  759.             pBits = (PBITS) &Object[ObjectList->nEntry];
  760.             *pBits |= put_enum(data, pszEntry, WimpColour, ELEMENTS(WimpColour), FALSE) << wimp_ICON_FG_COLOUR_SHIFT;
  761.             if ((pszEntry = parse(data, pszIn, ObjectList->pData)) != NULL)
  762.               *pBits |= put_enum(data, pszEntry, WimpColour, ELEMENTS(WimpColour), FALSE) << wimp_ICON_BG_COLOUR_SHIFT;
  763.             break;
  764.           default:
  765.             error("Unknown iol_ value (%d)", ObjectList->nTable);
  766.             break;
  767.           }
  768.         }
  769.       break;
  770.     }
  771.   }
  772. LOG(("-----"));
  773. }
  774.  
  775.  
  776. void get_objects(FILE * hf, PSTR pszStringTable, PSTR pszMessageTable, PSTR Object, POBJECTLIST ObjectList, int nObjects, int nIndent)
  777. {
  778. PSTR pszIndent;
  779. PBITS pBits;
  780. PINT pInt;
  781. PSHORT pShort;
  782. PBYTE pByte;
  783. int i, n;
  784.  
  785. pszIndent = (nIndent == 1) ? "  " : (nIndent == 2) ? "    " : "";
  786. LOG(("get_objects"));
  787. for (n = 0; n < nObjects; n++, ObjectList++)
  788.   {
  789. LOG(("Item:%s\tOffset:%d\tType:%d", ObjectList->pszEntry, ObjectList->nEntry, ObjectList->nTable));
  790.   if (ObjectList->nTable != iol_OBJECT)
  791.     { // do nothing for res2text
  792.     fputs(pszIndent, hf);
  793.     switch (ObjectList->nTable)
  794.       {
  795.       case iol_MSG:
  796.       case iol_STRING:
  797.         get_string(hf, pszStringTable, pszMessageTable, Object, (PSTRINGLIST) ObjectList, pszIndent);
  798.         break;
  799.       case iol_TSTRING:
  800.         get_tstring(hf, pszStringTable, Object, (PSTRINGLIST) ObjectList, pszIndent);
  801.         break;
  802.       case iol_FLAGS:
  803.         pBits = (PBITS) &Object[ObjectList->nEntry];
  804.         get_flags(hf, ObjectList->pszEntry, *pBits, (PFLAGS) ObjectList->pData, ObjectList->nData);
  805.         break;
  806.       case iol_IFLAGS:
  807.         pBits = (PBITS) &Object[ObjectList->nEntry];
  808.         get_iflags(hf, ObjectList->pszEntry, *pBits);
  809.         break;
  810.       case iol_BFLAGS:
  811.         pByte = (PBYTE) &Object[ObjectList->nEntry];
  812.         get_flags(hf, ObjectList->pszEntry, *pByte, (PFLAGS) ObjectList->pData, ObjectList->nData);
  813.         break;
  814.       case iol_ENUM:
  815.         pInt = (int *) &Object[ObjectList->nEntry];
  816.         get_enum(hf, ObjectList->pszEntry, *pInt, (PFLAGS) ObjectList->pData, ObjectList->nData, FALSE);
  817.         break;
  818.       case iol_CMP:
  819.         pInt = (int *) &Object[ObjectList->nEntry];
  820.         get_enum(hf, ObjectList->pszEntry, *pInt, CmpFlags, ELEMENTS(CmpFlags), TRUE);
  821.         break;
  822.       case iol_OSCOL:
  823.         pInt = (int *) &Object[ObjectList->nEntry];
  824.         get_enum(hf, ObjectList->pszEntry, *pInt, OsColours, ELEMENTS(OsColours), FALSE);
  825.         break;
  826.       case iol_BOX:
  827.         get_box(hf, ObjectList->pszEntry, (os_box *) &Object[ObjectList->nEntry]);
  828.         break;
  829.       case iol_BITS:
  830.         pBits = (PBITS) &Object[ObjectList->nEntry];
  831.         if (*pBits == ~0 && ObjectList->nData == bits_ACTION)
  832.           fprintf(hf, "%s\n", ObjectList->pszEntry);
  833.         else
  834.           fprintf(hf, "%s&%x\n", ObjectList->pszEntry, *pBits);
  835.         break;
  836.       case iol_INT:
  837.         pInt = (PINT) &Object[ObjectList->nEntry];
  838.         fprintf(hf, "%s%d\n", ObjectList->pszEntry, *pInt);
  839.         break;
  840.       case iol_SHORT:
  841.         pShort = (PSHORT) &Object[ObjectList->nEntry];
  842.         fprintf(hf, "%s%d\n", ObjectList->pszEntry, (int) *pShort);
  843.         break;
  844.       case iol_BYTE:
  845.         pByte = (PBYTE) &Object[ObjectList->nEntry];
  846.         fprintf(hf, "%s%d\n", ObjectList->pszEntry, (bits) *pByte);
  847.         break;
  848.       case iol_COORD:
  849.         get_coord(hf, ObjectList->pszEntry, (os_coord *) &Object[ObjectList->nEntry]);
  850.         break;
  851.       case iol_SPRITE:
  852.         pBits = (PBITS) &Object[ObjectList->nEntry];
  853.         fprintf(hf, "%s&%x\n", ObjectList->pszEntry, *pBits);
  854.         break;
  855.       case iol_PSTR:
  856.         get_pstr(hf, ObjectList->pszEntry, Object, ObjectList->nEntry, ObjectList->nData);
  857.         break;
  858.       case iol_ESG:
  859.         pBits = (PBITS) &Object[ObjectList->nEntry];
  860.         fprintf(hf, "%s%d\n", ObjectList->pszEntry, (*pBits & wimp_ICON_ESG) >> wimp_ICON_ESG_SHIFT);
  861.         break;
  862.       case iol_WCOL:
  863.         pByte = (PBYTE) &Object[ObjectList->nEntry];
  864.         get_enum(hf, ObjectList->pszEntry, *pByte, WimpColour, ELEMENTS(WimpColour), FALSE);
  865.         break;
  866.       case iol_BCOLS:
  867.         pBits = (PBITS) &Object[ObjectList->nEntry];
  868.         i = (*pBits & wimp_ICON_FG_COLOUR) >> wimp_ICON_FG_COLOUR_SHIFT;
  869.         get_enum(hf, ObjectList->pszEntry, i, WimpColour, ELEMENTS(WimpColour), FALSE);
  870.         fputs(pszIndent, hf);
  871.         i = (*pBits & wimp_ICON_BG_COLOUR) >> wimp_ICON_BG_COLOUR_SHIFT;
  872.         get_enum(hf, ObjectList->pData, i, WimpColour, ELEMENTS(WimpColour), FALSE);
  873.         break;
  874.       default:
  875.         error("Unknown iol_ value (%d)", ObjectList->nTable);
  876.         break;
  877.       }
  878.     }
  879.   }
  880. LOG(("-----"));
  881. }
  882.  
  883.  
  884. #define min(a,b) ((a)<(b)?(a):(b))
  885. // Iconbar {
  886. // returns "Iconbar\0" and sets pszIn to byte after '{'
  887. PSTR next_object(PSTR * pszIn, PSTR pszEnd)
  888. {
  889.     PSTR p, q;
  890.     int cb;
  891.     char ch;
  892.     static char achObject[48];
  893.  
  894.     p = *pszIn;
  895.     while ((ch = *p++) != '{') {
  896.         if (ch == '}' || p >= pszEnd) {
  897.             return(NULL);
  898.         }
  899.     }
  900. // p points to char *after* the brace
  901.     *pszIn = p--;
  902.     while (*(p - 1) <= ' ') p--;    // skip trailing spaces
  903.     *p = '\0';
  904.     q = p;
  905.     while (*(q - 1) > ' ') q--;        // find start of name to return
  906.     cb = min((int) (p - q), sizeof(achObject) - 1);
  907.     memcpy(achObject, q, cb);
  908.     achObject[cb] = '\0';
  909.     *p = ' ';
  910.     return(&achObject[0]);
  911. }
  912.  
  913.  
  914. PSTR object_end(PDATA data, PSTR pszIn, PSTR pszEnd)
  915. {
  916.     PSTR p;
  917.     int nDepth;
  918.     char ch;
  919.  
  920.     nDepth = 1;
  921.     p = pszIn;
  922.     while (nDepth > 0) {
  923.         if ((ch = *p++) == ':' || ch == '#') {  // skip values and comments
  924.             while (*p++ >= ' ') {
  925.                 if (p >= pszEnd) {
  926.                     report(data, pszIn, "Missing brace }");
  927.                     return(NULL);
  928.                 }
  929.             }
  930.         } else {
  931.             if (ch == '{') {
  932.                 nDepth++;
  933.             } else if (ch == '}') {
  934.                 nDepth--;
  935.             }
  936.             if (p >= pszEnd) {
  937.                 report(data, pszIn, "Missing brace }");
  938.                 return(NULL);
  939.             }
  940.         }
  941.     }
  942.     return(p);
  943. }
  944.  
  945.  
  946. void _object(FILE * hf, PDATA data, PSTR pszIn, PSTR pszOut, PCLASSES pClass)
  947. {
  948.     toolbox_relocatable_object_base * object;
  949.     PINT pReloc;
  950.     PSTR strings;
  951.     int cb, ref;
  952.  
  953.     object = (toolbox_relocatable_object_base *) pszOut;
  954.     object->rf_obj.class_no = pClass->class_no;
  955.     put_objects(data, pszIn, 0, (PSTR) &object->rf_obj, ObjectHeaderList, ELEMENTS(ObjectHeaderList));
  956.     object->rf_obj.body_size = pClass->t2o(data, pszIn, object);
  957.  
  958.     strings = (PSTR) (object + 1) + object->rf_obj.body_size;
  959.     if ((ref = data->StringTable.ref) == 0) {
  960.         object->string_table_offset = -1;
  961.     } else {
  962.         object->string_table_offset = (int) ((PSTR) strings - (PSTR) object);
  963.         memcpy(strings, data->StringTable.pstr, ref);
  964.         strings += ALIGN(ref);
  965.     }
  966.     if ((ref = data->MessageTable.ref) == 0) {
  967.         object->message_table_offset = -1;
  968.     } else {
  969.         object->message_table_offset = (int) ((PSTR) strings - (PSTR) object);
  970.         memcpy(strings, data->MessageTable.pstr, ref);
  971.         strings += ALIGN(ref);
  972.     }
  973.     if (data->RelocTable.ref == 0) {
  974.         object->relocation_table_offset = -1;
  975.     } else {
  976.         object->relocation_table_offset = (int) ((PSTR) strings - (PSTR) object);
  977.         pReloc = (PINT) strings;
  978.         *pReloc++ = data->RelocTable.ref;
  979.         cb = data->RelocTable.ref * sizeof(RELOC);
  980.         memcpy((PSTR) pReloc, (PSTR) data->RelocTable.pReloc, cb);
  981.         strings = (PSTR) pReloc;
  982.         strings += cb;
  983.     }
  984.  
  985.     object->rf_obj.size = object->relocation_table_offset - (sizeof(toolbox_relocatable_object_base) - sizeof(object->rf_obj));
  986.     object->rf_obj.header_size = sizeof(object->rf_obj);
  987.     cb = (int) ((PSTR) strings - (PSTR) object);
  988.     fwrite(pszOut, cb, 1, hf);
  989.     memset(pszOut, 0, cb);
  990. }
  991.  
  992.  
  993. void object(FILE * hf, toolbox_relocatable_object_base * object, object2text o2t)
  994. {
  995.     PSTR pszStringTable, pszMessageTable;
  996.  
  997.     pszStringTable = pszMessageTable = NULL;
  998.     if (object->string_table_offset != -1) {
  999.         pszStringTable = ((PSTR) object) + object->string_table_offset;
  1000.     }
  1001.     if (object->message_table_offset != -1) {
  1002.         pszMessageTable = ((PSTR) object) + object->message_table_offset;
  1003.     }
  1004.  
  1005. LOG(("StringTable:%d", object->string_table_offset));
  1006. LOG(("MessageTable:%d", object->message_table_offset));
  1007.  
  1008. //LOG(("size:%d", template->rf_header.size));
  1009. //LOG(("header_size:%d", template->rf_header.header_size));
  1010. //LOG(("body_size:%d", template->rf_header.body_size));
  1011.  
  1012.     get_objects(hf, pszStringTable, pszMessageTable, (PSTR) &object->rf_obj, ObjectHeaderList, ELEMENTS(ObjectHeaderList), 1);
  1013.     o2t(hf, (toolbox_resource_file_object_base *) &object->rf_obj, pszStringTable, pszMessageTable);
  1014. }
  1015.